#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#define BEEP_ON  0X100008
#define BEEP_OFF 0X100009

static void *gpiobase;
static unsigned long *gpiocaltfn0,*gpiocoutenb,*gpiocout;

static long beep_ioctl(struct file *file,
                    unsigned int cmd,
                    unsigned long arg){
    switch(cmd){
        case BEEP_ON:
            *gpiocout |= (1<<14);
            break;
        case BEEP_OFF:
            *gpiocout &= ~(1<<14);
            break;
        default:
            return -1;
    }
    return 0;
}

static struct file_operations beep_fops = {
    .owner = THIS_MODULE,
    .unlocked_ioctl = beep_ioctl,
};

static struct miscdevice beep_misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name  = "beep",
    .fops  = &beep_fops,
};

static int __init beep_drv_init(void){
    gpiobase=ioremap(0XC001C000,0X24);
    gpiocaltfn0=(unsigned long *)(gpiobase+0x20);
    gpiocoutenb=(unsigned long *)(gpiobase+0x04);
    gpiocout=(unsigned long *)(gpiobase);

    *gpiocaltfn0 &= ~(3<<28);
    *gpiocaltfn0 |= (1<<28);
    *gpiocoutenb |= (1<<14);
    *gpiocout &= ~(1<<14);

    misc_register(&beep_misc);
    return 0;
}

static void __exit beep_drv_exit(void){
    *gpiocout &= ~(1<<14);

    iounmap(gpiobase);

    misc_deregister(&beep_misc);

}

module_init(beep_drv_init);
module_exit(beep_drv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SGY");

